//显示图片分类
// #define d135240 1
#define CGRAM_OFFSET 		// for st7789 135x240 display
//#define d1352402 1
//#define d240240 1
//#define d2402402 1
#define d170320 1

#ifdef d135240
#include "d0_135240.jpg.h"
#include "d1_135240.jpg.h"
#include "d2_135240.jpg.h"
#include "d3_135240.jpg.h"

#include "d4_135240.jpg.h"
#include "d5_135240.jpg.h"
#include "d6_135240.jpg.h"
#include "d7_135240.jpg.h"

#include "d8_135240.jpg.h"
#include "d9_135240.jpg.h"

#define TFT_WIDTH  135  // ST7789 240 x 240 and 240 x 320
#define TFT_HEIGHT 240  // ST7789 240 x 240
// #define TFT_SCLK 13 //19 //17
// #define TFT_MOSI 23 //5
// #define TFT_RST  22 // Reset pin (could connect to RST pin)
// #define TFT_DC   18  // Data Command control pin
int CSArr[]={5,17,16,4};         //257A

#endif


//#include "Arduino.h"
#include "WiFi.h"
#include <WiFiManager.h>
#include <time.h>
#include <ArduinoJson.h>
#include <HTTPClient.h>
//#include <U8g2_for_Adafruit_GFX.h> 
#include <TJpg_Decoder.h>
#include <PNGdec.h>

#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include "changeHue.h"


          
//#include "img.h"
//#include "wea_qing.h"
//#include "wea_duoyun.h"
//#include "wea_xue.h"
//#include "wea_yin.h"
//#include "wea_yu.h"



#ifdef d240240
#include "d0_240240.jpg.h"
#include "d1_240240.jpg.h"
#include "d2_240240.jpg.h"
#include "d3_240240.jpg.h"

#include "d4_240240.jpg.h"
#include "d5_240240.jpg.h"
#include "d6_240240.jpg.h"
#include "d7_240240.jpg.h"

#include "d8_240240.jpg.h"
#include "d9_240240.jpg.h"
int CSArr[]={17,16,4,0};         //257C
#endif

#ifdef d2402402
#include "d0_2402402.jpg.h"
#include "d1_2402402.jpg.h"
#include "d2_2402402.jpg.h"
#include "d3_2402402.jpg.h"

#include "d4_2402402.jpg.h"
#include "d5_2402402.jpg.h"
#include "d6_2402402.jpg.h"
#include "d7_2402402.jpg.h"

#include "d8_2402402.jpg.h"
#include "d9_2402402.jpg.h"
int CSArr[]={17,16,4,0};         //257C
#endif





//1.9寸
#ifdef d170320
#include "d0_170320.jpg.h"
#include "d1_170320.jpg.h"
#include "d2_170320.jpg.h"
#include "d3_170320.jpg.h"

#include "d4_170320.jpg.h"
#include "d5_170320.jpg.h"
#include "d6_170320.jpg.h"
#include "d7_170320.jpg.h"

#include "d8_170320.jpg.h"
#include "d9_170320.jpg.h"

#define TFT_WIDTH  170 // ST7789 240 x 240 and 240 x 320
#define TFT_HEIGHT 320 // ST7789 240 x 240

// #define TFT_SCLK 13  //19 //17
// #define TFT_MOSI 23 //5
// #define TFT_RST  22 // Reset pin (could connect to RST pin)
// #define TFT_DC   18  // Data Command control pin

//int CSArr[]={5,17,16,4};         //257A
int CSArr[]={9,10,20,21,0};        //258K
#define Disp_Info 2
#define Disp_Min1 3
#define Disp_Min2 4
#endif

#include "qing.png.h"
#include "yin.h"
#include "yun.h"
#include "yu.h"
#include "xue.h"



#define NTP1 "ntp1.aliyun.com"
#define NTP2 "ntp2.aliyun.com"
#define NTP3 "ntp3.aliyun.com"

#define DISP_COUNT (sizeof(CSArr)/sizeof(CSArr[0]))
#define TFT_GRAY 0xBDF7
#define COLOR_GRAY 0x7BEF
#define dotx 120
#define SHOWPNG(img,x,y) showPng(((uint8_t*)img),sizeof(img),(x),(y))
#define MAX_IMAGE_WIDTH 240

const char* ssid1 = "comicyu_2f";
const char* password1 = "67799706100";

const char* ssid = "ChinaNet-yu";
const char* password = "ydd200706";
//U8G2_FOR_ADAFRUIT_GFX u8g2;

const uint8_t * digitArr[10] = {d0,d1,d2,d3,d4,d5,d6,d7,d8,d9};//,&da10};//,&da11,&da12};
const int sizeArr[10]={sizeof(d0),sizeof(d1),sizeof(d2),sizeof(d3),sizeof(d4),sizeof(d5),sizeof(d6),sizeof(d7),sizeof(d8),sizeof(d9)};
String wea_Desc="";
String wea_Temp="";
String wea_TempRange="24-35";
String wea_TempH="35";
String wea_TempL="24";
String wea_Wind="";
String Weather_date="";
int weekday=0;
int month=8;
int day=23;

String Weather_temp_night="";
String Weather_reportdate="";
String  Weather_desc_day;
String  Weather_desc_night;

int icount=0;
struct tm timeinfo_last;
PNG png;

// #define CS1 5
// #define CS2 17
// #define CS3 16
// #define CS4 4

TFT_eSPI tft = TFT_eSPI();       // Invoke custom library


//int CSArr[]={19,18,17,4};      //249x


//unsigned int current_hue=-1;     //当前色调 0-360; 

void initDisplayCSs()
{
  for(int i=0;i<DISP_COUNT;i++){
    pinMode(CSArr[i],OUTPUT);
    digitalWrite(CSArr[i],HIGH);
  }
}

void enableAllDisps(int sw){
  for(int i=0;i<DISP_COUNT;i++){
    digitalWrite(CSArr[i],sw);
  }
}

void activeAllDisps(){
  enableAllDisps(LOW);
}

void deactiveAllDisps(){
  enableAllDisps(HIGH);
}

void activeDisp(int index){
  digitalWrite(CSArr[index], LOW);
}

void deactiveDisp(int index){
  digitalWrite(CSArr[index], HIGH);
}

void drawDigit(int disp,int digit,int x)
{
  Serial.printf("-drawDigit-disp,digit,x:%d,%d,%d \n\r",disp,digit,x);
  activeDisp(disp);
  //tft.drawRGBBitmap(x,0,(*digitArr[digit]).pixels,da0.width,da0.height);
  TJpgDec.drawJpg(x,0,digitArr[digit],sizeArr[digit]);
  deactiveDisp(disp);
}

bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) {
  //更改色调,使用当前的色调值
  //changeHue(bitmap,w,h);
  tft.pushImage(x, y, w, h, bitmap);   // 也可换成 DMA 版本
  return 1;                            // 继续解码下一块
}


void setup() {
  clearScreens();
  Serial.begin(115200);

  //----初始化屏幕，st7735 4disp board only
  // #ifdef ST7735_4DISP
  //   Serial.println("初始化st7735 4屏幕");
  //   initScreens();
  //   delay(1000);
  // #endif
  //--------------------

  Serial.println("initDisplayCSs..");
  initDisplayCSs();
  // We need to 'init' both displays
  // at the same time. so set both cs pins low
  Serial.println("ActiveAllDisps..");
  activeAllDisps();
  tft.init();
  tft.setTextSize(2);
  // Set both cs pins HIGH, or 'inactive'
  Serial.println("Deactive all Disps..");
  deactiveAllDisps();
  tft.setTextSize(1);

  printBoth("Connect to Wifi.");
  connectWifi();
  configTime(8*3600,0,NTP1,NTP2,NTP3);
  delay(1000);

  printBoth("Initialized");
  //u8g2.begin(tft);
  //printBoth("started u8g2,about to set chinese font..");
  // u8g2.setFont(u8g2_font_wqy16_t_gb2312a);

  // u8g2.setForegroundColor(TFT_WHITE);      // apply Adafruit GFX color
  // u8g2_2.setForegroundColor(TFT_BLUE);      // apply Adafruit GFX color
  // u8g2_3.setForegroundColor(TFT_BLUE);      // apply Adafruit GFX color

  // u8g2.setCursor(10,80);  
  printBoth("getting time..");
  
  timeinfo_last.tm_hour=-1;
  timeinfo_last.tm_min=-1;

  struct tm timeinfo;
  while(!getLocalTime(&timeinfo, 1000))
  {
    delay(1000); 
    printBoth(".");   
  }
  printBoth("got time.");

clearScreens();
TJpgDec.setCallback(tft_output);
//TJpgDec.setJpgScale(2); 
TJpgDec.setSwapBytes(true);
//---------------------------------- original multiple tft test-------------------
  // /*
  //  Update the first screen
  //  all 'tft.' call must be done
  //  after setting the cs pin low
  // */
  // activeDisp(0);
  // //digitalWrite(CSArr[0], LOW);
  // //tft.setRotation(1);  
  // tft.fillScreen(TFT_RED);
  // tft.setCursor(0,10);
  // tft.print("Hello World.\nI'm display #1");
  // // set the cs pin back to HIGH when finished
  // // with this particular display
  // deactiveDisp(0);


  // // Update the second screen
  // activeDisp(1);
  // //tft.setRotation(2);  
  // tft.fillScreen(TFT_GREEN);
  // tft.setCursor(0,10);
  // tft.print("Hello World.\nI'm display #2");
  // deactiveDisp(1);

  // activeDisp(2);
  // tft.fillScreen(TFT_BLUE);
  // tft.setCursor(0,10);
  // tft.print("Hello World.\nI'm display #3");
  // deactiveDisp(2);

  // activeDisp(3);
  // tft.fillScreen(TFT_YELLOW); 
  // tft.setCursor(0,10);
  // tft.print("Hello World.\nI'm display #4");
  // deactiveDisp(3);


}

void printBoth(const char* str)
{
  Serial.print(str);
  activeDisp(0);
  tft.print(str);
  deactiveDisp(0);
}

void connectWifi()
{

  //WiFiManager wifiManager;
  
  //wifiManager.autoConnect("YuClockAP");

  
  int ic=0;
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

while (WiFi.status() != WL_CONNECTED)
{
  printBoth("Connect to Wifi:");
  printBoth(ssid);
  ic=0;
  WiFi.begin(ssid, password);
  delay(1000);
  while (WiFi.status() != WL_CONNECTED && ic<20) {  
    printBoth("-");
    delay(1000);
    ic++;
  }
  
  if(WiFi.status() != WL_CONNECTED)
  {
  ic=0;

  printBoth("Change to Wifi:");
  printBoth(ssid1);

  WiFi.begin(ssid1, password1);
  delay(1000);
  while (WiFi.status() != WL_CONNECTED && ic<10) {  
    printBoth("-");
    delay(1000);
    ic++;
  }
  }
  }
  printBoth("WiFi connected!");
  
}

int ic=0;
int firstShow=0;

void loop() {
  // put your main code here, to run repeatedly:
  if(ic%60==0){
    current_hue++;
    current_hue=current_hue%360;
  }

  if(ic%600==0)
  {
    getWeather();
  }
  //Serial.print("printLocalTime:");
  printLocalTime();
  ic=(ic+1)%3000;
  delay(1000);
}


void clearScreen(int index){
    activeDisp(index);
    tft.fillScreen(TFT_BLACK);
    tft.fillRect(0, 0, TFT_WIDTH, TFT_HEIGHT,TFT_BLACK);
    deactiveDisp(index);
}

void clearScreens()
{
  for(int i=0;i<DISP_COUNT;i++){
      clearScreen(i);
  }
}


void printLocalTime() {
  time_t now;
  now=time(NULL);
  //if (getLocalTime(&timeinfo, 1000)) { // 5000ms超时时间
  struct tm * ltm=localtime(&now);

  {
    // 成功获取时间，格式化并打印
    if(firstShow==0)
    {
      firstShow++;
      tft.fillScreen(TFT_BLACK);
    }
    //String weekdays[]={"SUN","MON","TUE","WED","THR","FRI","SAT"};
    //weekday = weekdays[ltm->tm_wday];
    weekday = ltm->tm_wday;
    month=ltm->tm_mon;
    day=ltm->tm_mday;
    //String currentTime = String(asctime(&timeinfo));
    String currentTime = String(asctime(ltm));
    currentTime.trim(); // 移除字符串尾部的换行符

    if(timeinfo_last.tm_min != ltm->tm_min){
      printDigitHour(ltm->tm_hour,timeinfo_last.tm_hour,timeinfo_last.tm_hour==0 ||ltm->tm_sec==0);
      printDigitMin(ltm->tm_min,timeinfo_last.tm_min,timeinfo_last.tm_min==0 ||ltm->tm_sec==0);  
    }
    showSeconds(ltm->tm_sec);

    timeinfo_last.tm_hour = ltm->tm_hour;
    timeinfo_last.tm_min = ltm->tm_min;

  }
}


//#define TFT_WIDTH 128
int switchWeatherOrDot=0;
#define SEC_H 2
void showSeconds(int sec)
{
  int SEC_Y = TFT_HEIGHT-2;
  int disp = Disp_Info; //sec/15;
  //int width = ((sec % 15)+1) * TFT_WIDTH / 15;
  // int width = (sec+1) * TFT_WIDTH / 60;
  // activeDisp(disp);  
  // //清除Sec
  // if(sec==0 || sec==1)
  // {
  //     tft.fillRect(0,SEC_Y,TFT_WIDTH,SEC_H,TFT_BLACK); //ColorArr[2]);     
  // }
  // //画蓝色条
  // tft.fillRect(0,SEC_Y,width,SEC_H,TFT_BLUE);
  // deactiveDisp(disp);

  if(sec % 10==0){
    switchWeatherOrDot=1-switchWeatherOrDot;
    
    if(switchWeatherOrDot==0){
        //清屏,显示天气,图标,温度
      clearScreen(disp);
      showWeatherImg();
      showWeatherText();
    }
  }
  
  
  if(switchWeatherOrDot!=0)
  {
      //显示两个点
    if(sec%2==0){
      clearScreen(disp);
    }
    else{
      activeDisp(disp);  
      tft.fillCircle(TFT_WIDTH / 2 ,130,15,TFT_BLUE);
      tft.fillCircle(TFT_WIDTH / 2 ,230,15,TFT_BLUE);
      deactiveDisp(disp);
    }

  }
  
  
  
  
}


void showWeatherText()
{

  int y= TFT_HEIGHT / 2;
  activeDisp(Disp_Info);
  tft.setFreeFont(&FreeSans24pt7b);
  tft.setTextColor(TFT_WHITE);  //#888-8410     
  tft.setCursor(28,80);
  tft.setTextSize(1);
  tft.printf("%02d %02d",month+1,day);
  
  tft.setTextColor(TFT_GREEN);  //#888-8410     
  tft.setCursor(80,y+60);
  tft.print(wea_Temp);
  
  tft.setCursor(110,90);
  tft.setTextFont(4);
  tft.printf("[%d]",weekday);
  //tft.setTextSize(2);
  // //tft.setCursor(0,y);
  // //tft.print(wea_TempRange);
  
  deactiveDisp(Disp_Info);
}

void showWeatherImg()
{
    int weax=-5;
    int weay= TFT_HEIGHT/2;  // 140; //TFT_HEIGHT-40;
    
    activeDisp(Disp_Info);
    if(wea_Desc.indexOf("晴")>=0)
      SHOWPNG(qing,weax,weay);
    else if (wea_Desc.indexOf("阴")>=0)
      SHOWPNG(yin,weax,weay);
    else if (wea_Desc.indexOf("雨")>=0)
      SHOWPNG(yu,weax,weay);
    else if (wea_Desc.indexOf("雪")>=0)
      SHOWPNG(xue,weax,weay);
    else
      SHOWPNG(yun,weax,weay);
    deactiveDisp(Disp_Info);
}

typedef struct my_private_struct
{
  int xoff, yoff; // corner offset
} PRIVATE;

void pngDraw(PNGDRAW *pDraw) {
  uint16_t lineBuffer[MAX_IMAGE_WIDTH];
  uint8_t  maskBuffer[1 + MAX_IMAGE_WIDTH / 8];  // Mask buffer
  png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
  PRIVATE *pPriv = (PRIVATE *)pDraw->pUser;
  if (png.getAlphaMask(pDraw, maskBuffer, 255)) {
    tft.pushMaskedImage(pPriv->xoff, pPriv->yoff + pDraw->y, pDraw->iWidth, 1, lineBuffer,maskBuffer);
  }
}


void showPng(uint8_t* img,int size,int x,int y)
{
  PRIVATE priv;
  int rc, i = 0;
  rc = png.openRAM(img,size, pngDraw);
  if (rc == PNG_SUCCESS) {
      //Serial.printf("image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
      priv.xoff = x;
      priv.yoff = y;
      rc = png.decode((void *)&priv, 0);
      png.close();
  }
}


//转成2个字符长度的String
String to2Ch(int v)
{
  String s=String(v);
  if(v<10)
    s="0"+s;
  return s;
}


void printDigitHour(int h,int lasth,bool clearScr)
{
    
  //int h1 = (h>12?h-12:h)/10;
  //int h2 = (h>12?h-12:h)%10;

  int h1 = h/10;
  int h2 = h%10;
  
  //if(lasth!=h)
  //{
  drawDigit(0,h1,0);
  drawDigit(1,h2,0);
  //}
    
  //u8g2.setCursor(0,50);
  //tft.setCursor(10,50);
  //printBoth("Beijing weather:");
  //u8g2.println(Weather_date);
  //u8g2.println(Weather_desc);

  //Serial.println( Weather_desc_day + "-" +  Weather_desc_night);
  //Serial.println(Weather_temp+" ("+ Weather_temp_day + "-" + Weather_temp_night +")");
  //Serial.println(Weather_wind);
    
}

void printDigitMin(int v,int lastv,bool clearScr)
{ 
  if(v!=lastv)
  {
    int v1 = v/10;
    int v2 = v%10;
    drawDigit(Disp_Min1,v1,0);
    drawDigit(Disp_Min2,v2,0);
  }
}

void getWeather()
{
 
      String wea = getWeatherReq("base");
      if(wea.length()>0)
      {
        StaticJsonDocument<300> doc;
        deserializeJson(doc,wea);
      
        wea_Desc=String((const char *)doc["lives"][0]["weather"]);
        wea_Temp=String((const char *)doc["lives"][0]["temperature"]);
        wea_Wind=String((const char *)doc["lives"][0]["winddirection"])+String((const char *)doc["lives"][0]["windpower"]);
        Weather_reportdate=String((const char *)doc["lives"][0]["reporttime"]).substring(0,10);
      }
      Serial.print("getWeather() -- got Weather.");
      if(Weather_date!=Weather_reportdate)
      {
        Serial.print("Weather_date!=Weather_reportdate..");
        wea = getWeatherReq("all");
        if(wea.length()>0)
        {
          StaticJsonDocument<1500> doc;
          deserializeJson(doc,wea);
          Serial.println(wea);
          Weather_date=String((const char *)doc["forecasts"][0]["casts"][0]["date"]);
          Weather_desc_day=String((const char *)doc["forecasts"][0]["casts"][0]["dayweather"]);
          Weather_desc_night=String((const char *)doc["forecasts"][0]["casts"][0]["nightweather"]);
          wea_TempH=String((const char *)doc["forecasts"][0]["casts"][0]["daytemp"]);
          wea_TempL=String((const char *)doc["forecasts"][0]["casts"][0]["nighttemp"]);
        }
      }
  
}

String getWeatherReq(String base)
{
  String result="";
  Serial.println("Getting weather ...");
  String url = "https://restapi.amap.com/v3/weather/weatherInfo?parameters&key=e094cccaa9f94c734344ab015d8b4ec6&city=110000&extensions="+base+"&output=JSON";
  HTTPClient http;
  http.begin(url);
  int httpCode=http.GET();
  if(httpCode>0)
    result = http.getString();
  Serial.println(result);
  return result;
}

